/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.controller.grant;

import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.mvc.AbstractPlatformController;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.service.MetaResourceService;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.rbac.annotation.ControllerAuditLog;
import com.je.rbac.cache.*;
import com.je.rbac.exception.RoleException;
import com.je.rbac.service.grant.RbacGrantFuncPermissionService;
import com.je.rbac.service.grant.RbacGrantMenuPermissionService;
import com.je.rbac.service.grant.role.RbacGrantRoleService;
import com.je.rbac.service.permission.GrantTypeEnum;
import com.je.rbac.service.permission.PermissionLoadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 角色授权
 */
@RestController
@RequestMapping(value = "/je/rbac/cloud/grant/develop")
public class RbacGrantDevelopController extends AbstractPlatformController {

    @Autowired
    private RbacGrantRoleService rbacGrantRoleService;
    @Autowired
    private RbacGrantMenuPermissionService rbacGrantMenuPermissionService;
    @Autowired
    private RbacGrantFuncPermissionService rbacGrantFuncPermissionService;
    @Autowired
    private FuncPermissionCache funcPermissionCache;
    @Autowired
    private AccountProductCache accountProductCache;
    @Autowired
    private MetaResourceService metaResourceService;
    @Autowired
    private PermissionLoadService permissionLoadService;

    /**
     * 添加角色分类
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/addFolder"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "addDevelopRoleFolder",operateTypeName = "添加开发角色文件夹",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult addRoleModule(HttpServletRequest request) {
        String folderName = getStringParameter(request, "folderName");
        String remark = getStringParameter(request, "remark");
        String iconCls = getStringParameter(request, "icon");
        if (Strings.isNullOrEmpty(folderName)) {
            return BaseRespResult.errorResult("角色分类名称不能为空！");
        }
        DynaBean folderBean = rbacGrantRoleService.insertFolder(folderName, iconCls, remark, true);
        return BaseRespResult.successResult(folderBean, "添加角色分类成功！");
    }

    /**
     * 更新角色分类
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/updateFolder"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "updateDevelopRoleFolder",operateTypeName = "更新开发角色文件夹",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult updateFolder(HttpServletRequest request) {
        String folderId = getStringParameter(request, "folderId");
        String folderName = getStringParameter(request, "folderName");
        if (Strings.isNullOrEmpty(folderId)) {
            return BaseRespResult.errorResult("请选择需要更新的角色分类！");
        }
        if (Strings.isNullOrEmpty(folderName)) {
            return BaseRespResult.errorResult("角色分类名称不能为空！");
        }
        rbacGrantRoleService.updateFolder(folderId, folderName);
        return BaseRespResult.successResult("更新成功！");
    }

    /**
     * 删除角色分类
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/removeFolder"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "removeDevelopRoleFolder",operateTypeName = "移除开发角色文件夹",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult removeFolder(HttpServletRequest request) {
        String folderId = getStringParameter(request, "folderId");
        if (Strings.isNullOrEmpty(folderId)) {
            return BaseRespResult.errorResult("请选择需要删除的角色分类！");
        }
        try {
            rbacGrantRoleService.removeFolder(folderId);
        } catch (RoleException e) {
            return BaseRespResult.errorResult(e.getMessage());
        }
        return BaseRespResult.successResult("删除成功！");
    }

    /**
     * 添加角色
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/addRole"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "addDevelopRole",operateTypeName = "添加开发角色",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult addRole(HttpServletRequest request) {
        String parentId = getStringParameter(request, "parentId");
        String roleName = getStringParameter(request, "roleName");
        String baseRoleId = getStringParameter(request, "baseRoleId");
        String remark = getStringParameter(request, "remark");
        String iconCls = getStringParameter(request, "icon");
        String permGroupIds = getStringParameter(request, "permGroupIds");
        String permGroupNames = getStringParameter(request, "permGroupNames");

        if (Strings.isNullOrEmpty(roleName)) {
            return BaseRespResult.errorResult("角色名称不能为空！");
        }

        try {
            return BaseRespResult.successResult(rbacGrantRoleService.insertRole(parentId, roleName, permGroupIds, permGroupNames, baseRoleId, iconCls, remark, true), "添加角色成功！");
        } catch (RoleException e) {
            return BaseRespResult.errorResult(e.getMessage());
        }
    }

    /**
     * 更新角色
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/updateRole"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "updateDevelopRole",operateTypeName = "更新开发角色",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult updateRole(HttpServletRequest request) {
        String roleId = getStringParameter(request, "roleId");
        String roleName = getStringParameter(request, "roleName");
        String baseRoleId = getStringParameter(request, "baseRoleId");
        String remark = getStringParameter(request, "remark");
        String permGroupIds = getStringParameter(request, "permGroupIds");
        String permGroupNames = getStringParameter(request, "permGroupNames");

        if (Strings.isNullOrEmpty(roleId)) {
            return BaseRespResult.errorResult("请选择要更新的角色！");
        }

        if (Strings.isNullOrEmpty(roleName)) {
            return BaseRespResult.errorResult("角色名称不能为空！");
        }

        try {
            rbacGrantRoleService.updateRole(roleId, roleName, permGroupIds, permGroupNames, baseRoleId, remark);
        } catch (RoleException e) {
            return BaseRespResult.errorResult(e.getMessage());
        }

        return BaseRespResult.successResult("更新成功！");
    }

    /**
     * 删除角色
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/removeRole"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "removeDevelopRole",operateTypeName = "移除开发角色",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult removeRole(HttpServletRequest request) {
        String roleId = getStringParameter(request, "roleId");
        if (Strings.isNullOrEmpty(roleId)) {
            return BaseRespResult.errorResult("请选择需要删除的角色！");
        }
        try {
            rbacGrantRoleService.removeRole(roleId);
        } catch (RoleException e) {
            return BaseRespResult.errorResult(e.getMessage());
        }
        return BaseRespResult.successResult("删除成功！");
    }

    /**
     * 移动角色
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/moveRole"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "moveDevelopRole",operateTypeName = "移动开发角色/文件夹",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult moveRole(HttpServletRequest request) {
        String roleId = getStringParameter(request, "roleId");
        String targetId = getStringParameter(request, "targetId");
        String order = getStringParameter(request, "order");

        if (Strings.isNullOrEmpty(roleId)) {
            return BaseRespResult.errorResult("请选择要移动的角色！");
        }

        if (Strings.isNullOrEmpty(targetId)) {
            return BaseRespResult.errorResult("请选择目标角色或角色分类！");
        }

        try {
            rbacGrantRoleService.move(roleId, targetId, Strings.isNullOrEmpty(order) ? null : Integer.valueOf(order), true);
        } catch (RoleException e) {
            return BaseRespResult.errorResult(e.getMessage());
        }

        return BaseRespResult.successResult("移动成功！");
    }

    /**
     * 加载角色树
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/loadRoleTree"}, method = RequestMethod.GET, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "loadDevelopRoleTree",operateTypeName = "加载开发角色树",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult loadRoleTree(HttpServletRequest request) {
        String refresh = getStringParameter(request, "refresh");
        //清空缓存并重新加载
        if ("1".equals(refresh)) {
            funcPermissionCache.clear();
            accountProductCache.clear();
            permissionLoadService.reloadAllDevelopRolePermCache();
        }

        //加载角色树逻辑
        String parentIds = getStringParameter(request, "parentIds");
        String[] parentIdArray = null;
        if (!Strings.isNullOrEmpty(parentIds)) {
            parentIdArray = parentIds.split(",");
        }
        JSONTreeNode rootNode = rbacGrantRoleService.buildRoleTree(true, parentIdArray);
        List<DynaBean> productBeanList = metaResourceService.selectByNativeQuery(NativeQuery.build().tableCode("JE_PRODUCT_MANAGE"));
        Map<String, DynaBean> productIconMap = new HashMap<>();
        for (int i = 0; productBeanList != null && !productBeanList.isEmpty() && i < productBeanList.size(); i++) {
            productIconMap.put(productBeanList.get(i).getStr("JE_PRODUCT_MANAGE_ID"), productBeanList.get(i));
        }
        recursiveSetTreeNodeIcon(rootNode, productIconMap);

        return BaseRespResult.successResult(rootNode);
    }

    /**
     * 递归设置节点图标
     *
     * @param node
     * @param productIconMap
     */
    private void recursiveSetTreeNodeIcon(JSONTreeNode node, Map<String, DynaBean> productIconMap) {
        if (node.getBean() != null) {
            if ("productRoleId".equals(node.getId())) {
                node.setIcon("fal fa-user");
            } else {
                if (node.getBean().containsKey("SY_PRODUCT_ID") && node.getBean().get("SY_PRODUCT_ID") != null
                        && !Strings.isNullOrEmpty(node.getBean().get("SY_PRODUCT_ID").toString())
                        && productIconMap.get(node.getBean().get("SY_PRODUCT_ID")) != null
                        && !Strings.isNullOrEmpty(productIconMap.get(node.getBean().get("SY_PRODUCT_ID")).getStr("PRODUCT_ICON"))) {
                    node.setIcon(productIconMap.get(node.getBean().get("SY_PRODUCT_ID").toString()).getStr("PRODUCT_ICON"));
                }
            }
        }

        if (node.getChildren() == null || node.getChildren().isEmpty()) {
            return;
        }

        for (JSONTreeNode eachChildNode : node.getChildren()) {
            recursiveSetTreeNodeIcon(eachChildNode, productIconMap);
        }

    }

    /**
     * 保存角色菜单授权
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/saveDevelopMenuPermission"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "saveDevelopRoleMenuPermission",operateTypeName = "更新开发角色菜单授权",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult saveDevelopMenuPermission(HttpServletRequest request) {
        String roleIds = getStringParameter(request, "roleIds");
        String addedStrData = getStringParameter(request, "addedStrData");
        String deletedStrData = getStringParameter(request, "deletedStrData");
        if (Strings.isNullOrEmpty(addedStrData) && Strings.isNullOrEmpty(deletedStrData)) {
            return BaseRespResult.errorResult("无数据操作！");
        }
        //更新权限
        rbacGrantMenuPermissionService.updateDevelopMenuPermissions(GrantTypeEnum.MENU, roleIds, addedStrData, deletedStrData);
        return BaseRespResult.successResult("保存授权成功！");
    }

    /**
     * 保存功能授权
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/saveDevelopFuncPermission"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "saveDevelopRoleFuncPermission",operateTypeName = "更新开发角色功能授权",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult saveDevelopFuncPermission(HttpServletRequest request) {
        String roleIds = getStringParameter(request, "roleIds");
        String addedStrData = getStringParameter(request, "addedStrData");
        String deletedStrData = getStringParameter(request, "deletedStrData");

        if (Strings.isNullOrEmpty(addedStrData) && Strings.isNullOrEmpty(deletedStrData)) {
            return BaseRespResult.errorResult("无数据操作！");
        }
        rbacGrantFuncPermissionService.updateDevelopFuncPermissions(GrantTypeEnum.FUNC, roleIds, addedStrData, deletedStrData);
        return BaseRespResult.successResult("保存授权成功！");
    }

    /**
     * 保存APP授权
     *
     * @param request
     * @return
     */
    @RequestMapping(value = {"/saveDevelopAppPermission"}, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @ControllerAuditLog(moduleName = "角色授权模块",operateTypeCode = "saveDevelopRoleAppPermission",operateTypeName = "更新开发角色APP授权",logTypeCode = "securityManage",logTypeName = "安全管理")
    public BaseRespResult saveDevelopAppPermission(HttpServletRequest request) {
        return BaseRespResult.errorResult("此版本不包括此功能！");
    }

}
